home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / nr4subr.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  8KB  |  392 lines

  1. /*
  2.  * nr4subr.c:  subroutines for net/rom transport layer.
  3.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  4.  * non-commercial distribution only.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "timer.h"
  11. #include "ax25.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include "lapb.h"
  15. #include <ctype.h>
  16.  
  17. /* Convert a net/rom transport header to host format structure.
  18.  * Return -1 if error, 0 if OK.
  19.  */
  20.  
  21. int
  22. ntohnr4(hdr,bpp)
  23. register struct nr4hdr *hdr ;
  24. struct mbuf **bpp ;
  25. {
  26.     char *getaxaddr() ;
  27.     char axbuf[AXALEN] ;
  28.     unsigned char tbuf[NR4MINHDR] ;
  29.  
  30.     if (pullup(bpp, (char *)tbuf, NR4MINHDR) < NR4MINHDR)
  31.         return -1 ;
  32.  
  33.     hdr->opcode = tbuf[4] ;
  34.  
  35.     switch (tbuf[4] & NR4OPCODE) {
  36.  
  37.         case NR4OPPID:            /* protocol ID extension */
  38.             hdr->u.pid.family = tbuf[0] ;
  39.             hdr->u.pid.proto = tbuf[1] ;
  40.             break ;
  41.  
  42.         case NR4OPCONRQ:        /* connect request */
  43.             hdr->u.conreq.myindex = tbuf[0] ;
  44.             hdr->u.conreq.myid = tbuf[1] ;
  45.             if (pullup(bpp,(char *)&(hdr->u.conreq.window), 1) < 1)
  46.                 return -1 ;
  47.             if (pullup(bpp,axbuf,AXALEN) < AXALEN)
  48.                 return -1 ;
  49.             (void)getaxaddr(&hdr->u.conreq.user,axbuf) ;
  50.             if (pullup(bpp,axbuf,AXALEN) < AXALEN)
  51.                 return -1 ;
  52.             (void)getaxaddr(&hdr->u.conreq.node,axbuf) ;
  53.             break ;
  54.  
  55.         case NR4OPCONAK:        /* connect acknowledge */
  56.             hdr->yourindex = tbuf[0] ;
  57.             hdr->yourid = tbuf[1] ;
  58.             hdr->u.conack.myindex = tbuf[2] ;
  59.             hdr->u.conack.myid = tbuf[3] ;
  60.             if (pullup(bpp,(char *)&(hdr->u.conack.window), 1) < 1)
  61.                 return -1 ;
  62.             break ;
  63.  
  64.         case NR4OPDISRQ:        /* disconnect request */
  65.             hdr->yourindex = tbuf[0] ;
  66.             hdr->yourid = tbuf[1] ;
  67.             break ;
  68.  
  69.         case NR4OPDISAK:        /* disconnect acknowledge */
  70.             hdr->yourindex = tbuf[0] ;
  71.             hdr->yourid = tbuf[1] ;
  72.             break ;
  73.  
  74.         case NR4OPINFO:            /* information frame */
  75.             hdr->yourindex = tbuf[0] ;
  76.             hdr->yourid = tbuf[1] ;
  77.             hdr->u.info.txseq = tbuf[2] ;
  78.             hdr->u.info.rxseq = tbuf[3] ;
  79.             break ;
  80.  
  81.         case NR4OPACK:            /* information acknowledge */
  82.             hdr->yourindex = tbuf[0] ;
  83.             hdr->yourid = tbuf[1] ;
  84.             hdr->u.ack.rxseq = tbuf[3] ;
  85.             break ;
  86.  
  87.         default:                /* what kind of frame is this? */
  88.             return -1 ;
  89.     }
  90.  
  91.     return 0 ;
  92. }
  93.  
  94.  
  95. struct mbuf *
  96. htonnr4(hdr)
  97. register struct nr4hdr *hdr ;
  98. {
  99.     static unsigned char hlen[NR4NUMOPS] = {5,20,6,5,5,5,5} ;
  100.     struct mbuf *rbuf ;
  101.     register char *cp ;
  102.     char *putaxaddr() ;
  103.     unsigned char opcode ;
  104.  
  105.     opcode = hdr->opcode & NR4OPCODE ;
  106.  
  107.     if (opcode >= NR4NUMOPS)
  108.         return NULLBUF ;
  109.  
  110.     if (hdr == (struct nr4hdr *)NULL)
  111.         return NULLBUF ;
  112.  
  113.     if ((rbuf = alloc_mbuf(hlen[opcode])) == NULLBUF)
  114.         return NULLBUF ;
  115.  
  116.     rbuf->cnt = hlen[opcode] ;
  117.     cp = rbuf->data ;
  118.  
  119.     cp[4] = hdr->opcode ;
  120.     
  121.     switch (opcode) {
  122.     
  123.         case NR4OPPID:
  124.             *cp++ = hdr->u.pid.family ;
  125.             *cp = hdr->u.pid.proto ;
  126.             break ;
  127.  
  128.         case NR4OPCONRQ:
  129.             *cp++ = hdr->u.conreq.myindex ;
  130.             *cp++ = hdr->u.conreq.myid ;
  131.             cp += 3 ;                        /* skip to sixth byte */
  132.             *cp++ = hdr->u.conreq.window ;
  133.             cp = putaxaddr(cp, &hdr->u.conreq.user) ;
  134.             (void) putaxaddr(cp, &hdr->u.conreq.node) ;
  135.             break ;
  136.  
  137.         case NR4OPCONAK:
  138.             *cp++ = hdr->yourindex ;
  139.             *cp++ = hdr->yourid ;
  140.             *cp++ = hdr->u.conack.myindex ;
  141.             *cp++ = hdr->u.conack.myid ;
  142.             cp++ ;                            /* already loaded pid */
  143.             *cp = hdr->u.conack.window ;
  144.             break ;
  145.  
  146.         case NR4OPDISRQ:
  147.             *cp++ = hdr->yourindex ;
  148.             *cp = hdr->yourid ;
  149.             break ;
  150.  
  151.         case NR4OPDISAK:
  152.             *cp++ = hdr->yourindex ;
  153.             *cp = hdr->yourid ;
  154.             break ;
  155.  
  156.         case NR4OPINFO:
  157.             *cp++ = hdr->yourindex ;
  158.             *cp++ = hdr->yourid ;
  159.             *cp++ = hdr->u.info.txseq ;
  160.             *cp = hdr->u.info.rxseq ;
  161.             break ;
  162.  
  163.         case NR4OPACK:
  164.             *cp++ = hdr->yourindex ;
  165.             *cp++ = hdr->yourid ;
  166.             *++cp = hdr->u.ack.rxseq ;    /* skip third byte (tricky yuck) */
  167.             break ;
  168.  
  169.     }
  170.  
  171.     return rbuf ;
  172. }
  173.  
  174.  
  175. /* Get a free circuit table entry, and allocate a circuit descriptor.
  176.  * Initialize control block circuit number and ID fields.
  177.  * Return a pointer to the circuit control block if successful,
  178.  * NULLNR4CB if not.
  179.  */
  180.  
  181. struct nr4cb *
  182. new_n4circ()
  183. {
  184.     int i ;
  185.     struct nr4cb *cb ;
  186.  
  187.     for (i = 0 ; i <  NR4MAXCIRC ; i++)        /* find a free circuit */
  188.         if (Nr4circuits[i].ccb == NULLNR4CB)
  189.             break ;
  190.  
  191.     if (i == NR4MAXCIRC)    /* no more circuits */
  192.         return NULLNR4CB ;
  193.  
  194.     if ((cb = Nr4circuits[i].ccb =
  195.          (struct nr4cb *)calloc(1,sizeof(struct nr4cb))) == NULLNR4CB)
  196.         return NULLNR4CB ;
  197.     else {
  198.         cb->mynum = i ;
  199.         cb->myid = Nr4circuits[i].cid ;
  200.         return cb ;
  201.     }
  202. }
  203.  
  204.  
  205. /* Set the window size for a circuit and allocate the buffers for
  206.  * the transmit and receive windows.  Set the control block window
  207.  * parameter.  Return 0 if successful, -1 if not.
  208.  */
  209.  
  210. int
  211. init_nr4window(cb, window)
  212. struct nr4cb *cb ;
  213. unsigned window ;
  214. {
  215.     
  216.     if (window == 0 || window > NR4MAXWIN) /* reject silly window sizes */
  217.         return -1 ;
  218.         
  219.     if ((cb->txbufs =
  220.          (struct nr4txbuf *)calloc(window,sizeof(struct nr4txbuf)))
  221.          == (struct nr4txbuf *)0)
  222.         return -1 ;
  223.  
  224.     if ((cb->rxbufs =
  225.          (struct nr4rxbuf *)calloc(window,sizeof(struct nr4rxbuf)))
  226.          == (struct nr4rxbuf *)0) {
  227.         free((char *)cb->txbufs) ;
  228.         cb->txbufs = (struct nr4txbuf *)0 ;
  229.         return -1 ;
  230.     }
  231.  
  232.     cb->window = window ;
  233.     
  234.     return 0 ;
  235. }
  236.  
  237.  
  238. /* Free a circuit.  Deallocate the control block and buffers, and
  239.  * increment the circuit ID.  No return value.
  240.  */
  241.  
  242. void
  243. free_n4circ(cb)
  244. struct nr4cb *cb ;
  245. {
  246.     unsigned circ ;
  247.  
  248.     if (cb == NULLNR4CB)
  249.         return ;
  250.  
  251.     circ = cb->mynum ;
  252.     
  253.     if (cb->txbufs != (struct nr4txbuf *)0)
  254.         free((char *)cb->txbufs) ;
  255.  
  256.     if (cb->rxbufs != (struct nr4rxbuf *)0)
  257.         free((char *)cb->rxbufs) ;
  258.  
  259.     /* Better be safe than sorry: */
  260.  
  261.     free_q(&cb->txq) ;
  262.     free_q(&cb->rxq) ;
  263.     
  264.     free((char *)cb) ;
  265.  
  266.     if (circ > NR4MAXCIRC)        /* Shouldn't happen. */
  267.         return ;
  268.         
  269.     Nr4circuits[circ].ccb = NULLNR4CB ;
  270.  
  271.     Nr4circuits[circ].cid++ ;
  272. }
  273.  
  274. /* See if any open circuit matches the given parameters.  This is used
  275.  * to prevent opening multiple circuits on a duplicate connect request.
  276.  * Returns the control block address if a match is found, or NULLNR4CB
  277.  * otherwise.
  278.  */
  279.  
  280. struct nr4cb *
  281. match_n4circ(index, id, user, node)
  282. int index ;                    /* index of remote circuit */
  283. int id ;                    /* id of remote circuit */
  284. struct ax25_addr *user ;    /* address of remote user */
  285. struct ax25_addr *node ;    /* address of originating node */
  286. {
  287.     int i ;
  288.     struct nr4cb *cb ;
  289.  
  290.     for (i = 0 ; i < NR4MAXCIRC ; i++) {
  291.         if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
  292.             continue ;        /* not an open circuit */
  293.         if (cb->yournum == index && cb->yourid == id
  294.             && addreq(&cb->user,user) && addreq(&cb->node,node))
  295.             return cb ;
  296.     }
  297.  
  298.     /* if we get to here, we didn't find a match */
  299.  
  300.     return NULLNR4CB ;
  301. }
  302.  
  303. /* Validate the index and id of a local circuit, returning the control
  304.  * block if it is valid, or NULLNR4CB if it is not.
  305.  */
  306.  
  307. struct nr4cb *
  308. get_n4circ(index, id)
  309. int index ;                /* local circuit index */
  310. int id ;                /* local circuit id */
  311. {
  312.     struct nr4cb *cb ;
  313.  
  314.     if (index >= NR4MAXCIRC)
  315.         return NULLNR4CB ;
  316.  
  317.     if ((cb = Nr4circuits[index].ccb) == NULLNR4CB)
  318.         return NULLNR4CB ;
  319.  
  320.     if (cb->myid == id)
  321.         return cb ;
  322.     else
  323.         return NULLNR4CB ;
  324. }
  325.  
  326. /* Return 1 if b is "between" (modulo the size of an unsigned char)
  327.  * a and c, 0 otherwise.
  328.  */
  329.  
  330. int
  331. nr4between(a, b, c)
  332. unsigned a, b, c ;
  333. {
  334.     if ((a <= b && b < c) || (c < a && a <= b) || (b < c && c < a))
  335.         return 1 ;
  336.     else
  337.         return 0 ;
  338. }
  339.  
  340. /* Set up default timer values, etc., in newly connected control block.
  341.  */
  342.  
  343. void
  344. nr4defaults(cb)
  345. struct nr4cb *cb ;
  346. {
  347.     int i ;
  348.     struct timer *t ;
  349.  
  350.     if (cb == NULLNR4CB)
  351.         return ;
  352.  
  353.     /* Set up the ACK and CHOKE timers */
  354.     
  355.     cb->tack.start = Nr4acktime / MSPTICK ;
  356.     cb->tack.func = nr4ackit ;
  357.     cb->tack.arg = (char *)cb ;
  358.  
  359.     cb->tchoke.start = Nr4choketime / MSPTICK ;
  360.     cb->tchoke.func = nr4unchoke ;
  361.     cb->tchoke.arg = (char *)cb ;
  362.  
  363.     cb->rxpastwin = cb->window ;
  364.  
  365.     /* Don't actually set the timers, since this is done */
  366.     /* in nr4sbuf */
  367.     
  368.     for (i = 0 ; i < cb->window ; i++) {
  369.         t = &cb->txbufs[i].tretry ;
  370.         t->func = nr4txtimeout ;
  371.         t->arg = (char *)cb ;
  372.     }
  373. }
  374.  
  375. /* See if this control block address is valid */
  376.  
  377. int
  378. nr4valcb(cb)
  379. struct nr4cb *cb ;
  380. {
  381.     int i ;
  382.  
  383.     if (cb == NULLNR4CB)
  384.         return 0 ;
  385.         
  386.     for (i = 0 ; i < NR4MAXCIRC ; i++)
  387.         if (Nr4circuits[i].ccb == cb)
  388.             return 1 ;
  389.  
  390.     return 0 ;
  391. }
  392.